注解配置 bean 普通组件:@Component,标识一个受Spring IOC容器管理的组件
持久化层组件:@Repository,标识一个受Spring IOC容器管理的持久化层组件
业务逻辑层组件:@Service,标识一个受Spring IOC容器管理的业务逻辑层组件
表述层控制器组件:@Controller,标识一个受Spring IOC容器管理的表述层控制器组件
@Repository,@Service,@Controller 都是由@Component 演化而来,他们之间的功能都是一样的,也就说可以用 @Component 的地方,其他三个也可以,区别就是名称不一样。
创建 Service 1 2 3 package com.itguigu.ioc.userMod.service;public interface UserService {}
1 2 3 4 5 6 7 8 9 10 11 package com.itguigu.ioc.userMod.service;import org.springframework.stereotype.Service;@Service public class UserServiceImpl implements UserService { public UserServiceImpl () { System.out.println("UserServiceImpl" ); } }
创建 Controller 1 2 3 4 5 6 7 8 9 10 11 package com.itguigu.ioc.userMod.controller;import org.springframework.stereotype.Controller;@Controller public class UserController { public UserController () { System.out.println("UserController" ); } }
创建 Dao 1 2 3 package com.itguigu.ioc.userMod.dao;public interface UserDao {}
1 2 3 4 5 6 7 8 9 10 11 package com.itguigu.ioc.userMod.dao;import org.springframework.stereotype.Repository;@Repository public class UserDaoImpl implements UserDao { public UserDaoImpl () { System.out.println("UserDaoImpl" ); } }
创建 xml 需要在 xml 中扫描组件,这样 Spring 才能管理有 @Controller,@Service,@Respository 的类,让其成为 spring 能管理的组件(bean)。也就是说加上注解后,Spring 会自动生成相应的 bean。且生成的 bean 的 id 是类名首字母的小写,即 userController, userServiceImpl, userDaoImpl。
base-package 属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类。
当需要扫描多个包时可以使用逗号分隔。
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd" > <context:component-scan base-package ="com.itguigu.ioc.userMod" > </context:component-scan > </beans >
测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.itguigu.ioc.userMod;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.itguigu.ioc.userMod.controller.UserController;import com.itguigu.ioc.userMod.dao.UserDao;import com.itguigu.ioc.userMod.dao.UserDaoImpl;import com.itguigu.ioc.userMod.service.UserService;import com.itguigu.ioc.userMod.service.UserServiceImpl;public class Test { public static void main (String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("user.xml" ); UserController userController = applicationContext.getBean("userController" , UserController.class ) ; System.out.println(userController); UserService userService = applicationContext.getBean("userServiceImpl" , UserServiceImpl.class ) ; System.out.println(userService); UserDao userDao = applicationContext.getBean("userDaoImpl" , UserDaoImpl.class ) ; System.out.println(userDao); } }
组件扫描范围 context:include-filter 的作用是,在指定的包结构下,再次通过注解或者类型的方式来指定需要包含的类。需要注意的是,需要将 use-default-filters
的值设置为 false,即关闭默认的过滤(默认是扫描包下所有的类)。
1 2 3 4 5 6 7 8 <context:component-scan base-package ="com.itguigu.ioc.userMod" use-default-filters ="false" > <context:include-filter type ="assignable" expression ="com.itguigu.ioc.userMod.service.UserServiceImpl" /> </context:component-scan >
context:include-filter 的作用是,在指定的包结构下,再次通过注解或者类型的方式来排除不需要包含的类。需要注意的是,需要将 use-default-filters
的值设置为 true,即允许默认的过滤(扫描包下所有的类)
1 2 3 4 5 6 7 <context:component-scan base-package ="com.itguigu.ioc.userMod" use-default-filters ="true" > <context:exclude-filter type ="assignable" expression ="com.itguigu.ioc.userMod.dao.UserDaoImpl" /> </context:component-scan >
注意⚠️:context:include-filter 中可以有多个包含,context:include-filter 下也可以有多个排除,但是两者不能同时使用。因为使用包含,那么剩下的就是不包含的,不包含的就没有必要在写出来了,反之同理。使用不包含,那么剩下的就是需要包含的。且 use-default-filts 在包含和不包含的情况下值不一样。
注解自动装配 在以前 controller 调用 service,service 调用 dao 的时候,都需要先实例话对象,然后在 对象.方法名 进行就行具体的调用,但是现在使用注解后我们可以直接使用 *@Autowired*
来代替以前的实例话对象。
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.itguigu.ioc.userMod.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import com.itguigu.ioc.userMod.service.UserService;@Controller public class UserController { @Autowired private UserService userService; public void addUser () { userService.addUser(); } public UserController () { System.out.println("UserController" ); } }
service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.itguigu.ioc.userMod.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.itguigu.ioc.userMod.dao.UserDao;@Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; public UserServiceImpl () { System.out.println("UserServiceImpl" ); } @Override public void addUser () { userDao.adduser(); } }
注解装配总结 组件 :指 Spring 管理的 bean
自动装配 :在需要赋值的非字面量属性上,加上 @Autowired,就可以在 Spring 容器中,通过不同的方式 (默认 byType,还可以 byName,或者多个时使用 Qualifier 指定) 匹配到相对应的 bean。
@Autowired 装配
会默认使用 byType 的方式,此时要求 Spring 容器中有且只有一个能够为其赋值,否则会报错(NoUniqueBeanDefinitionException)。
当 byType 实现不了装配时,会自动切换到 byName,此时要求 Spring 容器中有一个 bean 的 id 需要和属性名称一致。
若自动装配时匹配到多个可以赋值的 bean,我们可以使用 @Qualifier(value="bean id")
来指定使用哪一个 bean。
@Autowired 和 @Qualifier 可以一起做用于一个带形参的方法上,此时,@Qualifier(value=”bean id”) 所指定的 bean 作用于形参。
可以在四个注解后面直接设置该注解的 id。即 @Repository(“bean id”) …
@Autowired 上可以设置 reqired 属性,当 @Autowired(required = false) 时,如果装配不成功则不会报错,但是需要注意调用方法出现空指针异常。
基于注解的组件化管理 :
@Repository,@Service,@Controller,@Component 四个注解功能完全相同,不过实际开发中,要在实现不同功能的类上加上相应的注解。
完成组件化管理的过程:
在需要被 Spring 管理的类上加上相应的注解
在配置文件中通过 <context:component-scan>
对所设置的包结构进行扫描,就会将加上注解的类,作为 Spring 的组件进行加载(会自动在 Spring 的配置文件中生成相对应的 bean,这些 bean 的 id 就是类名称的首字母小写。)
@Resource 和 @Autowired 功能一样,只是默认加载顺序不一样,@Autowired 是先 byType 然后 byName。而 @Resource 则相反。
@Inject 和 @Autowired 注解一样也是按类型注入匹配的 bean,但没有 reqired 属性。
代码地址